home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / winterp-1.13 / src-server / w_utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-04  |  13.0 KB  |  350 lines

  1. /* -*-C-*-
  2. ********************************************************************************
  3. *
  4. * File:         w_utils.c
  5. * RCS:          $Header: w_utils.c,v 1.5 91/03/24 18:49:22 mayer Exp $
  6. * Description:  Various X Functionality
  7. * Author:       Niels Mayer, HPLabs
  8. * Created:      Fri Sep 29 01:24:38 1989
  9. * Modified:     Thu Oct  3 21:23:14 1991 (Niels Mayer) mayer@hplnpm
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       X11r5 contrib tape release
  13. *
  14. * WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
  15. * XLISP version 2.1, Copyright (c) 1989, by David Betz.
  16. *
  17. * Permission to use, copy, modify, distribute, and sell this software and its
  18. * documentation for any purpose is hereby granted without fee, provided that
  19. * the above copyright notice appear in all copies and that both that
  20. * copyright notice and this permission notice appear in supporting
  21. * documentation, and that the name of Hewlett-Packard and David Betz not be
  22. * used in advertising or publicity pertaining to distribution of the software
  23. * without specific, written prior permission.  Hewlett-Packard and David Betz
  24. * make no representations about the suitability of this software for any
  25. * purpose. It is provided "as is" without express or implied warranty.
  26. *
  27. * HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  28. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  29. * IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  30. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  31. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  32. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  33. * PERFORMANCE OF THIS SOFTWARE.
  34. *
  35. * See ./winterp/COPYRIGHT for information on contacting the authors.
  36. * Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  37. * Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  38. *
  39. ********************************************************************************
  40. */
  41. static char rcs_identity[] = "@(#)$Header: w_utils.c,v 1.5 91/03/24 18:49:22 mayer Exp $";
  42.  
  43. #include <stdio.h>
  44. #include <Xm/Xm.h>
  45. #include <X11/cursorfont.h>    /* defines XC_crosshair */
  46. #include "winterp.h"
  47. #include "user_prefs.h"
  48. #include "xlisp/xlisp.h"
  49.  
  50.  
  51. /******************************************************************************
  52.  ** (GET_MOUSE_LOCATION)
  53.  ** 
  54.  ** [ NEW ]:  it returns a dotted pair ... (root_x . root_y)
  55.  **
  56.  ** Primitive written by Richard Hess, Consilium, uunet!cimshop!rhess.
  57.  ** Fixes applied by Niels Mayer...
  58.  ******************************************************************************/
  59. LVAL Wut_Prim_GET_MOUSE_LOCATION()
  60. {
  61.   extern Display* display;    /* global in winterp.c */
  62.   extern Window   root_win;    /* global in winterp.c */
  63.   LVAL            lval_result, lval_x, lval_y;
  64.   int             x_rtn, y_rtn;
  65.   Window          junk1, junk2;
  66.   int             junk3, junk4;
  67.   unsigned int    junk5;
  68.   
  69.   /* protect some pointers -- added by NPM */
  70.   xlstkcheck(3);
  71.   xlsave(lval_x);
  72.   xlsave(lval_y);
  73.   xlsave(lval_result);
  74.  
  75.   if (!XQueryPointer(display, root_win, &junk1, &junk2,
  76.              &x_rtn, &y_rtn, &junk3, &junk4, &junk5))
  77.     xlerror("XQueryPointer() failed...");
  78.   lval_x = cvfixnum(x_rtn);
  79.   lval_y = cvfixnum(y_rtn);
  80.   lval_result = cons(lval_x, lval_y);
  81.  
  82.   /* restore the stack */
  83.   xlpopn(3);
  84.  
  85.   return (lval_result);
  86. }
  87.  
  88.  
  89. #ifdef hpux /* make this HPUX-only since sleepms() not portable */
  90. /******************************************************************************
  91.  * (X_REFRESH_DISPLAY [<sleep>])
  92.  * A kludgy hack to work around the Motif bug with refreshing and displaying popup
  93.  * status dialogues before embarking on a long computation. Use this function to
  94.  * work around cases where (send <widget> :update_display) isn't doing the right
  95.  * thing.
  96.  *
  97.  * The optional FIXNUM argument <sleep> is the number of milliseconds of sleep 
  98.  * time after popping up a shell before further expose events are procesed.
  99.  * The latter set of expose events correspond to drawing the "insides" of a
  100.  * popup dialog, e.g., the text and pixmaps.
  101.  *
  102.  * Note that making <sleep> too small means that the expose events generated
  103.  * by popping up a shell will not have time to round trip to the X server and
  104.  * back to the Motif client (WINTERP).
  105.  *
  106.  * If <sleep> is ommitted, then the sleeptime defaults to 300 millisecods.
  107.  * This time was empirically determined to be ok for my applications, but
  108.  * may not work if your workstation, X server, or network is slower than mine...
  109.  * As I said, this is a hack to work around a motif bug.
  110. ******************************************************************************/
  111. LVAL Wut_Prim_X_REFRESH_DISPLAY()
  112. {
  113.   extern sleepms();        /* from utils.c */
  114.   extern Display* display;    /* global in winterp.c */
  115.   extern LVAL true;
  116.   int sleeptime;
  117.   XEvent event;
  118.  
  119.   /* get optional <sleep> arg */
  120.   if (moreargs())
  121.     sleeptime = (int) getfixnum(xlgafixnum());
  122.   else
  123.     sleeptime = 300;        /* default value for <sleep> */
  124.  
  125.   xllastarg();
  126.  
  127.   XSync(display, FALSE);
  128.   while (XCheckMaskEvent(display, ExposureMask, &event))
  129.     XtDispatchEvent(&event);
  130.  
  131.   sleepms(sleeptime);
  132.  
  133.   XSync(display, FALSE);
  134.   while (XCheckMaskEvent(display, ExposureMask, &event))
  135.     XtDispatchEvent(&event);
  136.  
  137.   return (true);
  138. }
  139. #endif                /* hpux */
  140.  
  141.  
  142. /******************************************************************************
  143.  * (X_ALLOC_COLOR <color>)
  144.  * where <color> is a string, either a colorname from /usr/lib/X11/rgb.txt
  145.  * or a hexadecimal color specification "#RRGGBB".
  146.  * it returns a Pixel-value for the color.
  147. ******************************************************************************/
  148. LVAL Wut_Prim_XAllocColor()
  149. {
  150.   extern Display* display;    /* global in winterp.c */
  151.   extern Screen*  screen;    /* global in winterp.c */
  152.   extern Colormap colormap;    /* global in winterp.c */
  153.   XColor        screenColor;
  154.   LVAL          str_color;
  155.  
  156.   str_color = xlgastring();
  157.   xllastarg();
  158.   
  159.   if (!XParseColor(display, colormap, (String) getstring(str_color), &screenColor))
  160.     xlerror("XParseColor() couldn't parse color specification.", str_color);
  161.   if (!XAllocColor(display, colormap, &screenColor))
  162.     xlerror("XAllocColor() couldn't allocate specified color.", str_color);
  163.   return (cv_pixel(screenColor.pixel));
  164. }
  165.  
  166.  
  167. /******************************************************************************
  168.  * (X_STORE_COLOR <pixel> <color>)    [nicer would be (send <pixel> :store <color>)]
  169.  * where <color> is a string, either a colorname from /usr/lib/X11/rgb.txt
  170.  * or a hexadecimal color specification "#RRGGBB".
  171.  * it returns a Pixel-value for the color.
  172. ******************************************************************************/
  173. LVAL Wut_Prim_X_STORE_COLOR()
  174. {
  175.   extern Display* display;    /* global in winterp.c */
  176.   extern Screen*  screen;    /* global in winterp.c */
  177.   extern Colormap colormap;    /* global in winterp.c */
  178.   XColor        screenColor;
  179.   LVAL          str_color;
  180.   LVAL        lval_pixel;
  181.  
  182.   lval_pixel = xlga_pixel();
  183.   str_color = xlgastring();
  184.   xllastarg();
  185.   
  186.   screenColor.pixel = get_pixel(lval_pixel);
  187.   if (!XParseColor(display, colormap, (String) getstring(str_color), &screenColor))
  188.     xlerror("XParseColor() couldn't parse color specification.", str_color);
  189.   if (!XStoreColor(display, colormap, &screenColor))
  190.     xlerror("XStoreColor() couldn't allocate specified color.", str_color);
  191.   return (lval_pixel);
  192. }
  193.  
  194.  
  195. /******************************************************************************
  196.  * (X_ALLOC_N_COLOR_CELLS_NO_PLANES <num-cells>)
  197.  * returns an array of <num-cells> <pixel-objects> see Oliver Jones, p. 278
  198. ******************************************************************************/
  199. LVAL Wut_Prim_X_ALLOC_N_COLOR_CELLS_NO_PLANES()
  200. {
  201.   extern Display* display;    /* global in winterp.c */
  202.   extern Colormap colormap;    /* global in winterp.c */
  203.   Pixel*        pixels;
  204.   int        i, num_cells;
  205.   LVAL        result;
  206.  
  207.   num_cells = getfixnum(xlgafixnum());
  208.   xllastarg();
  209.   if (num_cells <= 0)
  210.     return (NIL);
  211.   
  212.   pixels = (Pixel*) XtMalloc((unsigned) (num_cells * sizeof(Pixel)));
  213.   XAllocColorCells(display, colormap, FALSE, NULL, 0, pixels, num_cells);
  214.  
  215.   xlsave1(result);
  216.   result = newvector(num_cells);
  217.   for (i = 0; i < num_cells; i++)
  218.     setelement(result, i, cv_pixel(pixels[i]));
  219.   xlpop();
  220.   XtFree(pixels);
  221.   return (result);
  222. }
  223.  
  224.  
  225. /******************************************************************************
  226.  * (GET_MOUSED_WIDGET)
  227.  * evaluating this function will change the cursor to a crossbar, indicating
  228.  * that the user is to 'click' the mouse to designate an object on the screen.
  229.  * If the user clicks on a visual item within WINTERP, this fucntion will
  230.  * return the WIDGETOBJ associated with the visual item. 
  231.  ******************************************************************************/
  232. LVAL Wut_UserClick_To_WidgetObj()
  233. {
  234.   extern Display* display;    /* global in winterp.c */
  235.   extern Window   root_win;    /* global in winterp.c */
  236.   extern LVAL     Wcls_WidgetID_To_WIDGETOBJ();    /* from w_classes.c */
  237.   extern XmGadget _XmInputInGadget(); /* in Xm/GadetUtils.c extern'd in XmP.h */
  238.   Cursor      cursor = XCreateFontCursor(display, XC_crosshair);
  239.   Window          parent_win, cur_win, child_win;
  240.   int             win_x, win_y;
  241.   Widget          widget_id, gadget_id;
  242.   XEvent      event;
  243.   Bool            xtc_ok;
  244.   
  245.   xllastarg();
  246.  
  247.   if (GrabSuccess != XGrabPointer(display, root_win, 0, ButtonPressMask|ButtonReleaseMask,
  248.                   GrabModeAsync, GrabModeAsync, None, cursor,
  249. #ifdef WINTERP_MOTIF_11
  250.                   XtLastTimestampProcessed(display)
  251. #else
  252.                   CurrentTime
  253. #endif                /* WINTERP_MOTIF_11 */
  254.                   ))
  255.     xlfail("GET_MOUSED_WIDGET -- couldn't grab pointer (XGrabPointer() failed).");
  256.   
  257.   XWindowEvent(display, root_win, ButtonPressMask, &event); /* remove the buttonpress from the queue*/
  258.   XWindowEvent(display, root_win, ButtonReleaseMask, &event); /* get the buttonrelease event */
  259.   XUngrabPointer(display,
  260. #ifdef WINTERP_MOTIF_11
  261.          XtLastTimestampProcessed(display)
  262. #else
  263.          CurrentTime
  264. #endif                /* WINTERP_MOTIF_11 */
  265.          );
  266.   XFlush(display);
  267.  
  268.   if (!event.xbutton.subwindow)
  269.     xlfail("GET_MOUSED_WIDGET aborted -- you clicked on the root window.");
  270.  
  271.   parent_win = event.xbutton.window; /* ASSERT event.xbutton.window == root_win, due to using XWindowEvent(root_win) */
  272.   win_x      = event.xbutton.x;
  273.   win_y      = event.xbutton.y;
  274.   cur_win    = event.xbutton.subwindow;
  275.   while ((xtc_ok = XTranslateCoordinates(display,
  276.                      parent_win, cur_win,
  277.                      win_x, win_y, /* give the x,y coords of event in parent_w */
  278.                      &win_x, &win_y, /* return the x,y coords relative to cur_win */
  279.                      &child_win)) /* returns child window of cur_win if that contains coords, else nil */
  280.      && child_win) {
  281. #ifdef DEBUG_WINTERP_1
  282.     fprintf(stderr, "parent_win=%lx, cur_win=%lx, child_win=%lx\n", parent_win, cur_win, child_win);
  283. #endif
  284.     parent_win = cur_win;
  285.     cur_win    = child_win;
  286.   }
  287.  
  288. #ifdef DEBUG_WINTERP_1
  289.   fprintf(stderr, "    Smallest window containing userclick is %lx\n", cur_win);
  290. #endif
  291.  
  292.   if (!xtc_ok)
  293.     xlfail("Bug in GET_MOUSED_WIDGET -- XTranslateCoordinates() failed.");
  294.  
  295.   if (!(widget_id = XtWindowToWidget(display, cur_win)))
  296.     xlfail("GET_MOUSED_WIDGET -- Couldn't find widget associated with window.\n    (Is the selected widget/window inside a different application?).\n");
  297.  
  298.   /* if the widget is a composite it may be managing a gadget -- attempt to retrieve it by looking up x,y coords in manager */
  299.   if (XtIsComposite(widget_id) &&
  300.       (gadget_id = (Widget) _XmInputInGadget(widget_id, win_x, win_y)))
  301.     return (Wcls_WidgetID_To_WIDGETOBJ(gadget_id)); /* then return the WIDGETOBJ assoc'd with gadget */
  302.   else
  303.     return (Wcls_WidgetID_To_WIDGETOBJ(widget_id)); /* otherwise, we return the WIDGETOBJ assoc'd with smallest window */
  304. }
  305.  
  306.  
  307. /******************************************************************************
  308.  * (load <fname> [:verbose] [:print])
  309.  *
  310.  * This function overrides xlisp/xlsys.c:xload(). All it does is check
  311.  * <fname> for '/' or '.' as the first character. If those don't exist, then
  312.  * the value of X resource "lispLibDir" is prepended and used as the filename.
  313.  * Note that "lispLibDir" should be the path to an existing directory with
  314.  * a trailing '/', e.g. "/usr/local/winterp/lisp-lib/"
  315.  ******************************************************************************/
  316. LVAL Wut_Prim_LOAD()
  317. {
  318.   extern LVAL k_verbose,k_print,true;
  319.   extern int xlgetkeyarg();    /* from xlisp/xlsubr.c */
  320.   extern char temptext[];    /* from winterp.c */
  321.   unsigned char *name;
  322.   int vflag,pflag;
  323.   LVAL arg;
  324.  
  325.   /* get the file name */
  326.   name = getstring(xlgetfname());
  327.  
  328.   /* get the :verbose flag */
  329.   if (xlgetkeyarg(k_verbose,&arg))
  330.     vflag = (arg != NIL);
  331.   else
  332.     vflag = TRUE;
  333.  
  334.   /* get the :print flag */
  335.   if (xlgetkeyarg(k_print,&arg))
  336.     pflag = (arg != NIL);
  337.   else
  338.     pflag = FALSE;
  339.  
  340.   /* load the file */
  341.   if ((name[0] != '/') && (name[0] != '.')) {
  342.     strcpy(temptext, user_prefs.lisp_lib_dir); /* prepend Xdefault 'lispLibDir', assume it has trailing '/' */
  343.     strcat(temptext, name);
  344.     return (xlload(temptext, vflag, pflag) ? true : NIL);
  345.   }
  346.   else
  347.     return (xlload(name, vflag, pflag) ? true : NIL);
  348. }
  349.